import { createDecorator } from 'vue-class-component'
import Vue, { ComponentOptions } from 'vue'
import LogUtil from '@src/util/log.ts'
import { isUndefined } from '@src/util/type'

// Declare Log decorator.
export const Log = createDecorator((options: ComponentOptions<Vue>, key) => {
  // Keep the original method for later.
  const originalMethod = options.methods?.[key] || function voidMethod() {}
  const componentName = options?.name
  
  // Wrap the method with the logging logic.
  const methods = options.methods || {}
  
  const wrapperMethod: (key: string) => (args: any[]) => void = function wrapperMethod(key: string) {
    // @ts-ignore
    const vm = this
    
    return function wrapperMethodHOC(...args) {
      // Print a log.
      LogUtil.info('', 'Invoked', `${componentName} -> ${key}`)
      
      // Invoke the original method
      originalMethod.apply(vm, args)
    }
    
  }
  
  if (isUndefined(key)) {
    for (const methodKey in methods) {
      methods[methodKey] = wrapperMethod(methodKey)
    }
  } else {
    methods[key] = wrapperMethod(key)
  }
  
})

export default Log